﻿// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// Copyright (c) 2011, Dr. Masroor Ehsan
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the author nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

using System;
using System.Collections.Generic;
using System.Reflection;
using FluentValidation;
using MaxTrader.Core;

namespace MaxTrader.BusinessObjects.Validation
{
    public class ValidationServiceLocator : Singleton<ValidationServiceLocator>, IServiceLocator
    {
        private readonly IDictionary<Type, object> _instantiatedServices;
        private readonly IDictionary<Type, Type> _servicesType;

        public ValidationServiceLocator()
        {
            _servicesType = new Dictionary<Type, Type>();
            _instantiatedServices = new Dictionary<Type, object>();

            BuildServiceTypesMap();
        }

        #region IServiceLocator Members

        object IServiceLocator.GetService<T>()
        {
            return GetService<T>();
        }

        #endregion

        public AbstractValidator<T> GetService<T>()
        {
            if (_instantiatedServices.ContainsKey(typeof (T)))
            {
                return (AbstractValidator<T>) _instantiatedServices[typeof (T)];
            }
            else
            {
                // LAZY INITIALIZATION
                try
                {
                    // USE REFLECTION TO INVOKE THE SERVICE
                    ConstructorInfo constructor = _servicesType[typeof (T)].GetConstructor(new Type[0]);
                    //Debug.Assert(constructor != null, "Cannot find a suitable constructor for " + typeof(T));

                    var service = (AbstractValidator<T>) constructor.Invoke(null);

                    // ADD THE SERVICE TO THE ONES THAT WE HAVE ALREADY INSTANTIATED
                    _instantiatedServices.Add(typeof (T), service);

                    return service;
                }
                catch (KeyNotFoundException)
                {
                    throw new ApplicationException("The requested service is not registered");
                }
            }
        }

        private void BuildServiceTypesMap()
        {
            _servicesType.Add(typeof (StockSector), typeof (StockSectorValidator));
        }
    }
}